package org.cyz.tools.common.util;

import org.apache.commons.lang3.reflect.MethodUtils;
import org.cyz.tools.core.assembly.log.Log;
import redis.clients.jedis.Client;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.exceptions.JedisException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author abccy
 * @title: CmdUtil
 * @projectName RedisGUI
 * @description: TODO
 * @date 2020-9-188:44
 */
public class CmdUtil extends RedisUtil {

    private final static List<String> cmds= Arrays.asList("PING","SET","GET","QUIT","EXISTS","DEL","UNLINK","TYPE","FLUSHDB","KEYS","RANDOMKEY","RENAME","RENAMENX",
            "RENAMEX","DBSIZE","EXPIRE","EXPIREAT","TTL","SELECT","MOVE","FLUSHALL","GETSET","MGET","SETNX","SETEX",
            "MSET","MSETNX","DECRBY","DECR","INCRBY","INCR","APPEND","SUBSTR","HSET","HGET","HSETNX","HMSET","HMGET",
            "HINCRBY","HEXISTS","HDEL","HLEN","HKEYS","HVALS","HGETALL","RPUSH","LPUSH","LLEN","LRANGE","LTRIM","LINDEX",
            "LSET","LREM","LPOP","RPOP","RPOPLPUSH","SADD","SMEMBERS","SREM","SPOP","SMOVE","SCARD","SISMEMBER","SINTER",
            "SINTERSTORE","SUNION","SUNIONSTORE","SDIFF","SDIFFSTORE","SRANDMEMBER","ZADD","ZRANGE","ZREM","ZINCRBY",
            "ZRANK","ZREVRANK","ZREVRANGE","ZCARD","ZSCORE","ZPOPMAX","ZPOPMIN","MULTI","DISCARD","EXEC","WATCH",
            "UNWATCH","SORT","BLPOP","BRPOP","AUTH","SUBSCRIBE","PUBLISH","UNSUBSCRIBE","PSUBSCRIBE","PUNSUBSCRIBE",
            "PUBSUB","ZCOUNT","ZRANGEBYSCORE","ZREVRANGEBYSCORE","ZREMRANGEBYRANK","ZREMRANGEBYSCORE","ZUNIONSTORE",
            "ZINTERSTORE","ZLEXCOUNT","ZRANGEBYLEX","ZREVRANGEBYLEX","ZREMRANGEBYLEX","SAVE","BGSAVE","BGREWRITEAOF",
            "LASTSAVE","SHUTDOWN","INFO","MONITOR","SLAVEOF","CONFIG","STRLEN","SYNC","LPUSHX","PERSIST","RPUSHX","ECHO",
            "LINSERT","DEBUG","BRPOPLPUSH","SETBIT","GETBIT","BITPOS","SETRANGE","GETRANGE","EVAL","EVALSHA","SCRIPT",
            "SLOWLOG","OBJECT","BITCOUNT","BITOP","SENTINEL","DUMP","RESTORE","PEXPIRE","PEXPIREAT","PTTL","INCRBYFLOAT",
            "PSETEX","CLIENT","TIME","MIGRATE","HINCRBYFLOAT","SCAN","HSCAN","SSCAN","ZSCAN","WAIT","CLUSTER","ASKING",
            "PFADD","PFCOUNT","PFMERGE","READONLY","GEOADD","GEODIST","GEOHASH","GEOPOS","GEORADIUS","GEORADIUS_RO",
            "GEORADIUSBYMEMBER","GEORADIUSBYMEMBER_RO","MODULE","BITFIELD","HSTRLEN","TOUCH","SWAPDB","MEMORY",
            "XADD","XLEN","XDEL","XTRIM","XRANGE","XREVRANGE","XREAD","XACK","XGROUP","XREADGROUP","XPENDING","XCLAIM",
            "ACL","XINFO","BITFIELD_RO");


    public static String executeSignCmd(String cmd){
        switch (cmd){
            case "INFO":
                break;
        }
        return cmd;
    }

    /**
     *
     * @param jedis
     * @param command
     * @param args
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static List<String> execRedisCommand(Jedis jedis, String command, String... args) throws InvocationTargetException, IllegalAccessException {
        if(null==jedis){
            jedis=RedisUtil.getClient();
        }
        Protocol.Command cmd = Protocol.Command.valueOf(command.toUpperCase());
        System.out.println(cmd);
        Client client = jedis.getClient();
        Method method = MethodUtils.getMatchingMethod(Client.class, "sendCommand", Protocol.Command.class, String[].class);
        method.setAccessible(true);
        method.invoke(client, cmd, args);
        try {
            List<String> respList = new ArrayList<>();
            Object response = client.getOne();
            if (response instanceof List) {
                for (Object itemResp : ((List) response)) {
                    respList.add(new String((byte[]) itemResp));
                }
                return respList;
            } else {
                if(null!=response){
                    return Collections.singletonList(new String((byte[]) response));
                }else{
                    return respList;
                }

            }

        } catch (JedisException e) {
            return Collections.singletonList(e.getMessage());
        }finally {
            closeClient(jedis);
        }
    }

    private static void closeClient(Jedis jedis) {
        if(null!=jedis){
            jedis.close();
        }
    }


    /**
     * 执行cmd命令
     *
     * @param command
     * @throws IOException
     */
    public static String executeCmd(String command) throws IOException {
        Log.info(CmdUtil.class.getSimpleName(),"Execute command : " + command);
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("cmd /c " + command);
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
        String line = null;
        StringBuilder build = new StringBuilder();
        while ((line = br.readLine()) != null) {
            Log.info(CmdUtil.class.getSimpleName(),line);
            build.append(line);
        }
        return build.toString();
    }

}
